//
//  EeWebViewRender.swift
//  SmoSky
//
//  Created by zhuxietong on 2018/8/23.
//  Copyright © 2018年 tianrun. All rights reserved.
//

import Foundation
import Eelay

import WebKit
import AsyncDisplayKit

open class MoWebNode : MoDisplayNode,TagsRenderDelegate{
    public func replace(_ tag: String) -> String {
        
        return self.delegete?.replace(tag) ?? ""
    }
    
    public weak var delegete:TagsRenderDelegate? = nil
    
    open override func willLayoutRules() {
        let web = self.node.view as! EeWebView
        web.delegete = self
    }
    
    public var node = ASDisplayNode { () -> UIView in
        let web = EeWebView()
        web.autoJustFrame = false
        return web
    }
    
    open var eeWeb: EeWebView{
        get{
            let web = self.node.view as! EeWebView
            web.delegete = self
            return web
        }
    }
    
    open var webView: WKWebView{
        get{
            let web = self.node.view as! EeWebView
            return web.webView
        }
    }
    
    open override func specGetter() -> _Spec {
        return _Spec.wrapper(node.Spec)
    }
    
    
}


open class WebNode : ASDisplayNode {
    public var eeWebView:EeWebView? = nil{
        didSet{
            if let web = eeWebView{
                view.addSubview(web)
            }
        }
    }
    
    open override func didLoad() {
        super.didLoad()
        guard let web = eeWebView else {
            return
        }
        view.addSubview(web)
    }
    
}

open class FixedWebCellNode:WebCellNode{
    open override func updateWebHeight() {
        
    }
}

open class WebCellNode : JoCellNode,TagsRenderDelegate{
    public var webModel = NSMutableDictionary()
    
    open var webNode:WebNode = WebNode()
    open func loadWeb(model:NSMutableDictionary)  {
        
    }
    open override func mo_model_willSet(new: NSMutableDictionary) {
//        print("---_OOOOOSss==",new)
        webModel = new
        _ = eeWebView
        eeWebView.webView.isOpaque = false
        eeWebView.webView.backgroundColor = ._background
              
    }
    
    
    
    open func updateWebHeight(){
        webModel["__height__"] = height
        let sec = webModel[int:"__section__",-1]
        let row = webModel[int:"__row__",-1]
        if sec == -1 || row == -1{
            active(ID: EeWebView.updateWebHeightKey, object: webModel)
            return
        }
        if let ctr = mo.controller as? ASListController{
            
            
            ctr.tableNode.performBatchUpdates({
                let path = IndexPath(row: row, section: sec)
                ctr.tableNode.reloadRows(at: [path], with: .none)
            }, completion: nil)
        }
        
        if let ctr = mo.controller as? ASColListController{
            ctr.collectionNode.performBatchUpdates({
                let path = IndexPath(item: row, section: sec)
                ctr.collectionNode.reloadItems(at: [path])
            }, completion: nil)
        }
        
    }
    public var height:CGFloat = Swidth{
        didSet{
          
            
            
            //            indexPathUpdate()
        }
    }
    
    
    open func replace(_ tag: String) -> String {
        return ""
    }

    
    
    open var eeWebView:EeWebView{
        get{
            if let web = mo.controller?.__extention["reuseID<\(webModel["reuseID","EeWebView"])>"] as? EeWebView //可复用处理
            {
                web.mo.model = webModel
                web.delegete = self
                web.changTheHeight = { [weak self]
                    h in
                    self?.height = h
                }
                webNode.eeWebView = web
                return web
            }else{
                let web = EeWebView()
                web.delegete = self
                web.changTheHeight = { [weak self]
                    h in
                    self?.height = h
                }
                mo.controller?.__extention["reuseID<\(webModel["reuseID","EeWebView"])>"] = web
                webNode.eeWebView = web
                loadWeb(model: webModel)
                return web
            }
        }
    }
    
    //    public weak var eeWebView:EeWebView? = nil{
    //        didSet{
    //            webNode.eeWebView = eeWebView
    //            eeWebView?.changTheHeight = { [weak self]
    //                h in
    //                self?.height = h
    //            }
    //        }
    //    }
    
    override open func specGetter() -> _Spec {
        let heigth = webNode.eeWebView?.webHeight ?? Sheight
        let h = webModel["__height__","\(heigth)"]
        return .inset([h,Swidth], .zero, child: webNode[h])
    }
    
    deinit {
        webNode.eeWebView?.delegete = nil
    }
    
}




public class EeWebView: JoView,TagsRenderDelegate,WKUIDelegate,WKNavigationDelegate{
    
    public weak var delegete:TagsRenderDelegate? = nil
    
    public func replace(_ tag: String) -> String {
        
        if let _d = self.delegete{
            return _d.replace(tag)
        }
        return repalceAction(tag)
    }
    
    
    public var load = false
    
    public var template:String = "商品图文"
    
    public var autoJustFrame = true
    
    
    public var defaultRender:BaseHTMLPage? = nil;
    
    
    public var render:BaseHTMLPage{
        
        if let _render = defaultRender{
            return _render
        }
        let path = Bundle.main.path(forResource: self.template, ofType: "html", inDirectory:"html/template")
        if path == nil{
            fatalError("EeWebView 未找到模版路径")
        }
        let render = TagsRender(templatePath: path!, model: 0)
        let media_path = Bundle.main.path(forResource: "html", ofType: nil)
        render.mediaBundlePath = media_path
        render.css_names = ["css/app"]
        render.delegate = self
        return render
    }
    
    
    public func load(template:String?=nil){
        //        if let tp = template
        //        {
        //               self.template = template
        //        }
        //
        webView.load(render: render)
    }
    
    public func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
        self.checkContentHeigth()
    }
    public func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
        self.checkContentHeigth()
    }
    
    public var repalceAction:(String)->String = { tag
        in return tag
    }
    public static let updateWebHeightKey = "updateWebHeight"
    public var __webView:WKWebView? = nil
    public var webView:WKWebView{
        get{
            if let v = self.__webView
            {
                return v
            }
            let config = WebConfiguration()
            config.initBlock = { hander,controller in
                controller.add(hander, name: "search")
                let appUserInfo = """
             function __getContentHeight() {
                let root = document.body;
                try {
                    let content = document.getElementById('fui-content')
                    if (content !== null){
                        root = content
                    }
                }catch (e) {

                }
              return root.scrollHeight
            }
            """
                let script11 = WKUserScript(source: appUserInfo, injectionTime: WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: true)
                let script12 = WKUserScript(source: appUserInfo, injectionTime: WKUserScriptInjectionTime.atDocumentEnd, forMainFrameOnly: true)
                
                controller.addUserScript(script11)
                controller.addUserScript(script12)
            }
            
            
            weak var wself = self
            config.receiveJsAction = {
                message,controller in
                if let one = message.body as? Dictionary<String, AnyObject>
                {
                    let dict = one.mutable_dictionary
                    wself?.receiveJsAction(object: dict)
                }
            }
            let rct = CGRect(x: 0, y: 0, width: Swidth, height: webHeight)
            let webV = WKWebView(frame: rct, configuration: config)
            let lays = [
                [webV,[ee.T.L.B.R]],
            ]
            self.setEeLays(lays: lays)
            self.__webView = webV
            return webV
            
        }
    }
    
    open func receiveJsAction(object:NSMutableDictionary)
    {
        
    }
    
    public var heightConstrain:NSLayoutConstraint = NSLayoutConstraint()
    public var changTheHeight:(CGFloat)->Void = {_ in}
    public required init() {
        super.init(frame: [0,0,Swidth,webHeight])
    }
    
    public var scrollView:UITableView? = nil
    {
        willSet{
            scrollView?.removeObserver(self, forKeyPath: "contentOffset")
        }
        didSet{
            let options: NSKeyValueObservingOptions = [NSKeyValueObservingOptions.new, NSKeyValueObservingOptions.old]
            scrollView?.addObserver(self, forKeyPath: "contentOffset", options: options, context: nil)
        }
    }
    
    
    public var webHeight:CGFloat = Swidth + 100
    required public init(frame: CGRect) {
        super.init(frame: [0,0,Swidth,webHeight])
        addLayoutRules()
    }
    
    required public init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override public func addLayoutRules() {
        webView.allowsBackForwardNavigationGestures = false
        webView.backgroundColor = ._background
        webView.scrollView.backgroundColor = ._background

        webView.uiDelegate = self
        webView.navigationDelegate = self
        let options: NSKeyValueObservingOptions = [NSKeyValueObservingOptions.new, NSKeyValueObservingOptions.old]
        webView.scrollView.addObserver(self, forKeyPath: "contentSize", options: options, context: nil)
        webView.translatesAutoresizingMaskIntoConstraints = false
        
        let lays = [
            [webView,[ee.T.L.B.R]],
        ]
        self.setEeLays(lays: lays)
    }
    
    
    public func updateHeight() {
        self.updateWeb(height: webView.scrollView.contentSize.height)
    }
    
    
    func checkContentHeigth() {
        if !autoJustFrame{
            //            webView.scrollView.isScrollEnabled = true
            return
        }
        //        webView.scrollView.isScrollEnabled = false
        
        webView.evaluateJavaScript("__getContentHeight()") {[weak self] (value, err) in
            if let v = value{
                let height = "\(v)".cg_floatValue
                
                guard let ws = self else {
                    return
                }
                if ws.webHeight != height{
                    ws.webHeight = height
                    let frame = ws.webView.frame
                    ws.webView.frame = CGRect(x: frame.origin.x, y: frame.origin.y, width: frame.width, height: ws.webHeight)
                    let frame1 = ws.frame
                    ws.frame = CGRect(x: frame1.origin.x, y: frame1.origin.y, width: frame1.width, height: ws.webHeight)
                    ws.updateWeb(height:height)
                    
                }
                
            }
        }
    }
    
    override public func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        
        if keyPath == "contentSize" {
            if webHeight != webView.scrollView.contentSize.height
            {
                //                self.checkContentHeigth()
                
                //                self.webHeight = webView.scrollView.contentSize.height
                //                webView.scrollView.isScrollEnabled = false
                //                let frame = webView.frame
                //                webView.frame = CGRect(x: frame.origin.x, y: frame.origin.y, width: frame.width, height: webHeight)
                //                let frame1 = self.frame
                //                self.frame = CGRect(x: frame1.origin.x, y: frame1.origin.y, width: frame1.width, height: webHeight)
                //                self.updateWeb(height: webView.scrollView.contentSize.height)
            }
        }
        
        if keyPath == "contentOffset" {
            if let scrollV = self.scrollView
            {
                //                if #available(iOS 11.0, *) {
                //                } else {
                if abs(scrollV.contentOffset.y - offset) > 70
                {
                    webView.setNeedsLayout()
                    offset = scrollV.contentOffset.y
                }
                //                }
            }
        }
        
    }
    
    public func updateWeb(height:CGFloat){
        webView.layoutIfNeeded()
        self.invalidateIntrinsicContentSize()
        
        self.layoutIfNeeded()
        self.superview?.layoutIfNeeded()
        
        //        if let tab = tableView
        //        {
        //            tab.beginUpdates()
        //            tab.endUpdates()
        //        }
        self.changTheHeight(height)
    }
    
    public var offset:CGFloat = 0
    public func updateWebContent(observer scrollView:UIScrollView) {
        if abs(scrollView.contentOffset.y - offset) > 70
        {
            webView.setNeedsLayout()
            offset = scrollView.contentOffset.y
        }
    }
    public var contentWidth:CGFloat = Swidth
    
    public override var intrinsicContentSize: CGSize
    {
        return [contentWidth,webHeight]
    }
    deinit {
        __webView?.scrollView.removeObserver(self, forKeyPath: "contentSize")
        scrollView?.removeObserver(self, forKeyPath: "contentOffset")
    }
    
}



